import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
// import App from './App';
import * as serviceWorker from './serviceWorker';
import { BrowserRouter } from 'react-router-dom';
import { observable, action, autorun, computed, configure, runInAction, when, reaction } from 'mobx';
import { observer } from 'mobx-react';
import store from './mobx/AppStore';

configure({
  // 强制要求 修改 observable 的数据，一定要放到 action 中
  enforceActions: 'observed',
});

// 1. 初始化 mobx 容器仓库
class MyStore {
  @observable count = 0;
  name = 'huangbiao';
  @observable foo = 'bar';
  @observable price = 10;
  @action.bound increment() {
    this.count++;
  }

  @computed get totalPrice() {
    console.log('totalPrice 这里使用了缓存，不是展示多少次，就调用多少次');
    return this.count * this.price;
  }

  // bound 表示上下文 this 为 实例对象，不能使用箭头函数
  @action.bound change() {
    console.log(this);
    this.foo = 'hello';
    this.foo = 'world';
    this.count = 10;
  }

  @action.bound asyncChange () {
    setTimeout(() => {
      // this.count = 100
      // 1. 定义 action 函数
      // this.changeCount()
      // 2. 直接调用action 
      // action('changeFoo', () => {
      //   this.count = 30
      // })()
      // 3. runInAction
      runInAction(() => {
        this.count = 40
      })
    }, 200)
  }

  @action.bound changeCount(value = 20) {
    this.count = value
  }
}

const mystore = new MyStore();

/**
 * auto 默认会执行一次
 * 然后，当内部所依赖的 observable 数据发生改变的时候重新触发执行
 */
autorun(() => {
  console.log('autorun: ', mystore.name, mystore.count, mystore.foo);
});

/****************** 修改多次observable会引发多次执行 autorun 函数 ******************** 
// 如果连续调用两次 observable 的数据，则 autorun 也会调用两次，效率比较低
// mystore.foo = 'hello'
// mystore.foo = 'world'
// mystore.count = 10
// 1. 将多次修改的操作 放到一个 action 中
// mystore.change()
// 2. runInAction 创建一个被立即调用的一次性 action。
// runInAction(() => {
//   mystore.foo = 'hello';
//   mystore.foo = 'world';
//   mystore.count = 10;
// })
*/

// const tempChnage = mystore.change
// 上下文已经不是 store对象了，因此需要使用 @action.bound 保证上下文
// tempChnage()

/****************** 异步触发会引发的问题 ******************** */
// mystore.asyncChange()

/****************** when ******************** 
// 当 count > 100 的时候，只执行一次自定义逻辑
when(
  () => {
    return mystore.count > 100
  },
  () => {
    console.log('when -> ', mystore.count)
  }
)
mystore.changeCount(200)
// when 满足条件只触发了一次
mystore.changeCount(300)
*/

/****************** 异步触发会引发的问题 ******************** */
reaction(
  () => {
    return mystore.count
  },
  (data, reaction) => {
    console.log('reaction -> ', data)
    // 手动停止当前 reaction 的监听
    if (data > 3) {
      reaction.dispose()
    }
  }
)


// 2. 在组件中使用 mobx 容器的状态
@observer
class App extends Component {
  render() {
    const { store } = this.props;
    return (
      <>
        <div>AppMobx</div>
        <div>{store.count}</div>
        <div>
          <button onClick={store.increment}>increment</button>
        </div>
        <div>总价：{store.totalPrice}</div>
        <div>总价：{store.totalPrice}</div>
        <div>总价：{store.totalPrice}</div>
        <div>总价：{store.totalPrice}</div>
        <div>总价：{store.totalPrice}</div>
        <div>总价：{store.totalPrice}</div>
        <div>总价：{store.totalPrice}</div>
      </>
    );
  }
}

// 3. 在组件中发起 action 修改容器的状态
ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      {/* <App/> */}
      <App store={mystore} />
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
